package com.activiti.ActivitiUtils.impl;

import com.activiti.ActivitiUtils.bean.Page;
import com.activiti.ActivitiUtils.bean.WrappedTaskBean;
import com.activiti.ActivitiUtils.builder.payload.task.TaskCompletePayload;
import com.activiti.ActivitiUtils.builder.payload.task.TaskQueryPayload;
import com.activiti.ActivitiUtils.builder.payload.task.TaskVariablePayload;
import com.activiti.ActivitiUtils.factory.TaskBeanWrappedFactory;
import com.activiti.ActivitiUtils.runtime.WrappedTaskRuntime;
import com.activiti.dao.RoleDAO;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * create by chongyahhh
 * 2020/4/4
 */

@Component
public class WrappedTaskRuntimeImpl implements WrappedTaskRuntime {
    @Autowired
    private TaskService taskService;
    @Autowired
    private RoleDAO roleDAO;

    private boolean checkUserMsg(){
        Session session = SecurityUtils.getSubject().getSession();
        String userId = (String)session.getAttribute("userId");
        if(userId == null){
            System.out.println("没有用户信息");
            return false;
        }
        List<String> candidateGroups = (List<String>)session.getAttribute("roles");
        if(candidateGroups == null || candidateGroups.isEmpty()){
            session.setAttribute("roles",roleDAO.getRolesByUserId(userId));
        }
        return true;
    }

    private TaskQuery crateTaskQueryWhenGetListOrPages(TaskQueryPayload taskPayload){
        boolean checked = false;
        if(taskPayload.getAssigneeId()==null && taskPayload.getGroups()==null){
            checked = this.checkUserMsg();
            if(!checked){
                return null;
            }
        }
        TaskQuery taskQuery = taskService.createTaskQuery();
        if(taskPayload.getParentTaskId() != null){
            taskQuery.taskParentTaskId(taskPayload.getParentTaskId());
        }
        if(taskPayload.getProcessInstanceId() != null){
            taskQuery.processInstanceId(taskPayload.getProcessInstanceId());
        }
        if(taskPayload.getProcessDefinitionKey() != null){
            taskQuery.processDefinitionKey(taskPayload.getProcessDefinitionKey());
        }
        if(taskPayload.getTaskDefinitionKey() != null){
            taskQuery.taskDefinitionKey(taskPayload.getTaskDefinitionKey());
        }
        if(checked){
            String userId = (String)SecurityUtils.getSubject().getSession().getAttribute("userId");
            List<String> candidateGroups = (List<String>)SecurityUtils.getSubject().getSession().getAttribute("roles");
            taskQuery.taskCandidateOrAssigned(userId,candidateGroups);
        } else {
            if(taskPayload.getAssigneeId() != null && taskPayload.getGroups() != null){
                taskQuery.taskCandidateOrAssigned(taskPayload.getAssigneeId(),taskPayload.getGroups());
            } else {
                if(taskPayload.getAssigneeId() != null){
                    taskQuery.taskAssignee(taskPayload.getAssigneeId());
                }
                if(taskPayload.getGroups() != null){
                    taskQuery.taskCandidateGroupIn(taskPayload.getGroups());
                }
            }
        }
        return taskQuery;
    }

    private Task task(String id) {
        Task task = taskService.createTaskQuery()
                .taskId(id)
                .singleResult();
        if(task == null){
            throw new RuntimeException("任务不存在");
        } else {
            return task;
        }
    }

    @Override
    public WrappedTaskBean getTask(String taskId) {
        Task task;
        try{
            task = this.task(taskId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return TaskBeanWrappedFactory.inject(task);
    }

    @Override
    public List<WrappedTaskBean> getTaskList(TaskQueryPayload taskPayload) {
        TaskQuery taskQuery = this.crateTaskQueryWhenGetListOrPages(taskPayload);
        List<Task> data = taskQuery.list();
        return TaskBeanWrappedFactory.inject(data);
    }

    @Override
    public Page<List<WrappedTaskBean>> getTaskWithPage(TaskQueryPayload taskPayload, Integer pageNum, Integer pageSize) {
        TaskQuery taskQuery = this.crateTaskQueryWhenGetListOrPages(taskPayload);
        Integer count = taskQuery.list().size();
        Integer totalPage = (count%pageSize==0)?(count/pageSize):(count/pageSize + 1);
        List<Task> data = taskQuery.orderByTaskCreateTime().asc().listPage((pageNum - 1) * pageSize,pageSize);
        return TaskBeanWrappedFactory.inject(data,pageNum,pageSize,totalPage);
    }

    @Override
    public WrappedTaskBean claim(String taskId){
        return this.claim(taskId,null);
    }

    @Override
    public WrappedTaskBean claim(String taskId,String assigneeId) {
        Task task;
        try{
            task = this.task(taskId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        if(task.getAssignee() != null && !task.getAssignee().isEmpty()){
            System.out.println("该任务已绑定");
            return null;
        }
        if(assigneeId != null){
            taskService.claim(task.getId(),assigneeId);
        } else {
            if(checkUserMsg()){
                String userId = (String)SecurityUtils.getSubject().getSession().getAttribute("userId");
                taskService.claim(task.getId(),userId);
            } else {
                return null;
            }
        }
        return TaskBeanWrappedFactory.inject(this.task(taskId));
    }

    @Override
    public WrappedTaskBean release(String taskId){
        return this.release(taskId,null);
    }

    @Override
    public WrappedTaskBean release(String taskId,String assigneeId) {
        Task task;
        try{
            task = this.task(taskId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        if(task.getAssignee() == null || task.getAssignee().isEmpty()){
            System.out.println("该任务没有负责人");
            return null;
        }
        String userId;
        if(assigneeId != null){
            userId = assigneeId;
        } else {
            if(checkUserMsg()){
                userId = (String)SecurityUtils.getSubject().getSession().getAttribute("userId");
            } else {
                return null;
            }
        }
        if (userId.equals(task.getAssignee())){
            taskService.unclaim(task.getId());
        } else {
            System.out.println("当前用户不为负责人");
            return null;
        }
        return TaskBeanWrappedFactory.inject(this.task(taskId));
    }

    @Override
    public WrappedTaskBean complete(TaskCompletePayload taskPayload) {
        return this.complete(taskPayload,false);
    }

    @Override
    public WrappedTaskBean complete(TaskCompletePayload taskPayload,boolean compel) {
        Task task;
        String userId;
        try{
            task = this.task(taskPayload.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        if(taskPayload.getAssigneeId() == null){
            if(checkUserMsg()){
                userId = (String)SecurityUtils.getSubject().getSession().getAttribute("userId");
            } else {
                return null;
            }
        } else {
            userId = taskPayload.getAssigneeId();
        }

        if(compel){
            taskService.setAssignee(task.getId(),userId);
            taskService.complete(task.getId(),taskPayload.getProcessVariables());
        } else {
            if(userId.equals(task.getAssignee())){
                taskService.complete(task.getId(),taskPayload.getProcessVariables());
            } else {
                System.out.println("该用户不是该任务的执行人，不能执行");
                return null;
            }
        }

        return TaskBeanWrappedFactory.inject(task);
    }

    @Override
    public Map<String, Map<String, Object>> getVariables(String taskId) {
        Task task;
        try {
            task = this.task(taskId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        Map<String, Map<String, Object>> data = new HashMap<>();
        data.put("local",task.getTaskLocalVariables());
        data.put("global",task.getProcessVariables());
        return data;
    }

    @Override
    public void setVariables(TaskVariablePayload taskPayload) {
        if(taskPayload.getTaskLocalVariables() != null){
            taskService.setVariablesLocal(taskPayload.getId(),taskPayload.getTaskLocalVariables());
        }
        if(taskPayload.getProcessVariables() != null){
            taskService.setVariables(taskPayload.getId(),taskPayload.getProcessVariables());
        }
    }

    @Override
    public void removeVariables(String taskId, List<String> variableNames) {
        taskService.removeVariables(taskId,variableNames);
    }
}
